﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Text;
using Microsoft.Practices.Unity;
using MiniStock.BusinessLogic.EntityPersister;
using MiniStock.BusinessLogic.EventDispatcher;
using MiniStock.BusinessLogic.EventDispatcher.MessageMap;
using MiniStock.BusinessLogic.EventProcessor.EventRepository;
using MiniStock.BusinessLogic.EventQueue.Queue;
using MiniStock.Entities;
using MiniStock.BusinessLogic.EventProcessor;
using MiniStock.Entities.Common;
using MiniStock.Entities.Common.Events;
using MiniStock.Entities.Stock;
using MiniStock.Entities.Stock.Events;
using MiniStock.Entities.Stock.Events.Customer;
using MiniStock.Infrastructure;
using MiniStock.Infrastructure.Configurator;
using MiniStock.Infrastructure.Queue;
using MiniStock.ServiceFacade;

namespace EventProcessorServiceHost
{
    class Program
    {
        public static void ConfigureGlobalContainer(IUnityContainer container)
        {
            container.RegisterType<IEventQueue, MsmqQueue>();
            container.RegisterType<IEventQueue, MsmqQueue>("InternalQueue");

            container.RegisterType<IPluginConfigurator, ConfigBasedConfigurator>(new ContainerControlledLifetimeManager());
            container.RegisterType<IEventDispatcherConfigurator, ConfigBasedConfigurator>(new ContainerControlledLifetimeManager());
            container.RegisterType<IEventProcessorConfigurator, ConfigBasedConfigurator>(new ContainerControlledLifetimeManager());
            container.RegisterType<IEventQueueConfigurator, ConfigBasedConfigurator>(new ContainerControlledLifetimeManager());
            container.RegisterType<IEventQueueConfigurator, ConfigBasedConfigurator>("InternalConfigurator", new ContainerControlledLifetimeManager());
            container.RegisterType<IEntityPersisterConfigurator, ConfigBasedConfigurator>(new ContainerControlledLifetimeManager());
        }

        public static void ConfigureContainer(IUnityContainer container)
        {
            container.RegisterType<IEventQueue, MemoryQueue>("DispatcherToProcessor", new ContainerControlledLifetimeManager());
            container.RegisterType<IEventQueue, MemoryQueue>("ProcessorToDispatcher", new ContainerControlledLifetimeManager());

            container.RegisterType<EventDispatcherLogic>(new ContainerControlledLifetimeManager());
            container.RegisterType<PersisterEventQueueWorker>(new ContainerControlledLifetimeManager());
            container.RegisterType<ProcessorEventQueueWorker>(new ContainerControlledLifetimeManager());
            container.RegisterType<EventDispatcherWorker>(new ContainerControlledLifetimeManager());
            container.RegisterType<EventProcessorWorker>(new ContainerControlledLifetimeManager());
            container.RegisterType<EntityPersisterWorker>(new ContainerControlledLifetimeManager());

            container.RegisterType<IRepository<EventProcessorEventData>, EventDbRepository>();
            container.RegisterType<IRepository<MessageMapRepositoryEntry>, MessageMapDbRepository>();

            // load customer plugin dll
            IProcessorPluginEntryPoint p = new PluginEntryPoint();
        }

        static void Main(string[] args)
        {
            MiniStockContext.OnConfigureGlobalContainer = ConfigureGlobalContainer;
            MiniStockContext.OnConfigureContainer = ConfigureContainer;

            Trace.Listeners.Add(new ConsoleTraceListener(false)
                                    {
                                        Filter = new EventTypeFilter(SourceLevels.Error)
                                    });

            using (var mss = new MiniStockContextScope())
            {
                var queueWorker = MiniStockContext.Current.RootContainer.Resolve<ProcessorEventQueueWorker>();
                var persisterWorker = MiniStockContext.Current.RootContainer.Resolve<PersisterEventQueueWorker>();
                var dispatcherWorker = MiniStockContext.Current.RootContainer.Resolve<EventDispatcherWorker>();

                queueWorker.Configure("Processor.1");
                persisterWorker.Configure();
                dispatcherWorker.Configure();
                queueWorker.Start();
                persisterWorker.Start();
                dispatcherWorker.Start();

                dispatcherWorker.Initialize();

                SerializationHelper.RegisterKnownEventTypes(new[] { typeof (CustomerEventBase) });

                using (var _commandHost = new ServiceHost(typeof(MiniStock.ServiceFacade.ServiceFacade), new Uri("http://localhost:999/command")))
                using (var _queryHost = new ServiceHost(typeof(MiniStock.ServiceFacade.Stock.StockServiceFacade), new Uri("http://localhost:999/query")))
                {

                    _commandHost.Open();
                    _queryHost.Open();

                    Console.Write("Press ENTER to finish");
                    Console.ReadLine();
                    //System.Windows.Forms.Application.Run(new MemoryQueueMonitoring());
                }

                dispatcherWorker.Stop();
                queueWorker.Stop();
                persisterWorker.Stop();
            }
        }
    }
}
